package com.atguigu.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Arrays;

/**
 * @author LOGIN
 * @title SecondKillService
 * @create 2025/6/16 19:02
 * @description
 */
@Service
public class SecondKillService {
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    /*public String secondkill(String skuId) {

        //1000个请求会生成1000个redis的decr key命令
        //redis使用单个线程接受处理： 他会一个个执行命令，下一个命令使用的库存一定是上一个命令计算完的结果
     stringRedisTemplate.opsForValue().decrement("sec:skuId:"+skuId);

        String stocker = stringRedisTemplate.opsForValue().get("sec:skuId:" + skuId);
        if (StringUtils.isEmpty(stocker)) {
            return "内存还未初始化";
        }
        int stock =Integer.parseInt(stocker);
        if (stock<=0) {
            return "库存不足";
        }
        //如果库存足够，使用 i-- 库存减 1 再更新到redis中
        stock--;
        stringRedisTemplate.opsForValue().set("sec:skuId:"+skuId,stock+"");
        return "success";*/
        /*
        * 原子性：
        *   1、redis单个命令具有原子性
        *          如果java代码只有redis操作的单个命令，那么这个方法具有原子性
        *           每个访问java代码的线程生成的redis命令， 交给redis都是一个个有序的执行，不会被中断
        *   2、如果业务中需要使用多个redis命令，并且使用了java代码
        *       java代码不加锁时，支持并发执行， 导致java整个方法不具有原子性，就会出现线程安全问题
        * kjsfkljfklsjflk
        * */

    public String secondkill(String skuId) {
        String script="local stock =tonumber(redis.call('get',KEYS[1])) " +
                "if stock >0 then redis.call('decr',KEYS[1])return 1 " +
                "else return 0 end";
        Boolean result = stringRedisTemplate.execute(new DefaultRedisScript<Boolean>(script, Boolean.class),
                Arrays.asList("sec:skuId:" + skuId, "keys2"), "arvg1", "arvg2");
        return result?"秒杀成功":"秒杀失败";
    }
}
